package de.ipk_gatersleben.bit.bi.edal.primary_data;

import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataDirectory;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataDirectoryException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataEntity;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataFile;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataFileException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.DateEvents;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.EdalDate;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.EnumDublinCoreElements;
import de.ipk_gatersleben.bit.bi.edal.primary_data.metadata.MetaDataException;

public class ZipThread extends Thread {

	private ZipOutputStream zout = null;
	private PrimaryDataDirectory directory = null;
	private CountDownLatch countDownLatch = null;

	public ZipThread(CountDownLatch countDownLatch, ZipOutputStream zout,
			PrimaryDataDirectory directory) {
		this.countDownLatch = countDownLatch;
		this.zout = zout;
		this.directory = directory;
	}

	@Override
	public void run() {
		try {
			readPrimaryDataDirectoryIntoZipOutputStream(this.zout,
					this.directory, true);
		} catch (PrimaryDataFileException | PrimaryDataDirectoryException e) {
			DataManager.getImplProv().getLogger().error(e.getMessage());
		} finally {
			this.countDownLatch.countDown();
		}
	}

	private void readPrimaryDataDirectoryIntoZipOutputStream(
			ZipOutputStream zout, PrimaryDataDirectory entity, boolean log)
			throws PrimaryDataDirectoryException, PrimaryDataFileException {

		try {
			if (log) {
				DataManager
						.getImplProv()
						.getLogger()
						.info("Preparing ZipOutputStream for '"
								+ entity.getName() + "'");
			}
			List<PrimaryDataEntity> files = entity.listPrimaryDataEntities();

			DataManager.getImplProv().getLogger()
					.debug("Adding directory " + entity.getPath());

			for (PrimaryDataEntity primaryDataEntity : files) {

				// if the file is directory, call the function recursively
				if (primaryDataEntity.isDirectory()) {
					readPrimaryDataDirectoryIntoZipOutputStream(zout,
							(PrimaryDataDirectory) primaryDataEntity, false);
					continue;
				}

				DataManager.getImplProv().getLogger()
						.debug("Adding file " + primaryDataEntity.getPath());

				ZipEntry zipEntry = new ZipEntry(primaryDataEntity.getPath()
						.substring(2));

				DateEvents dateEvents = null;
				try {
					dateEvents = primaryDataEntity.getMetaData()
							.getElementValue(EnumDublinCoreElements.DATE);
				} catch (MetaDataException e) {
					e.printStackTrace();
				}
				Set<EdalDate> set = dateEvents.getSet();

				long time = 0;

				for (EdalDate edalDate : set) {
					if (edalDate.getEvent().equals(
							EdalDate.STANDART_EVENT_TYPES.CREATED.toString())) {
						time = edalDate.getStartDate().getTimeInMillis();
						break;
					}
				}

				zipEntry.setTime(time);

				zout.putNextEntry(zipEntry);

				((PrimaryDataFile) primaryDataEntity).read(zout);

				zout.closeEntry();
			}
			if (log) {
				DataManager
						.getImplProv()
						.getLogger()
						.info("ZipOutputStream for '" + entity.getName()
								+ "' finished");
			}
		} catch (IOException e) {
			DataManager.getImplProv().getLogger()
					.error("unable to write zip streams : " + e.getMessage());
		}
	}
}
